package app.ui;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map.Entry;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.graphics.drawable.Drawable;
import android.location.Address;
import android.location.Criteria;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.GestureDetector;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import app.ui.RangeSeekBar.OnRangeSeekBarChangeListener;
import com.facebook.android.Facebook;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;

import database.local.Business;
import database.local.Comment;
import database.local.DataBaseClient;
import database.local.Deal;
import database.local.DrawableHolder;
import database.local.OverlayItemDrawable;
import database.local.PicturesUtil;
import database.local.QueryData;
import database.local.Utils;

public class AndroAppActivity extends MapActivity implements LocationListener {
	/** Called when the activity is first created. */
	GestureDetector mGestureDetector;
	private boolean isPopupExist = false, isDrinkVisible = true,
			isEatVisible = true, isPartyVisible = true;
	private ObservableMapView mapView;
	private View addPopupView;
	private MapController mapController;
	private LinearLayout timeLayout;
	private TextView timeText;
	private LocationManager lm;
	private Location location;
	private Calendar c;
	private String bestProvider;
	private Address currAddress;
	private Business currBusiness;
	private boolean CreateNewBusiness = false;
	private GeoPoint currentGeoPoint;
	private List<Business> allList;
	public DataBaseClient dbc = new DataBaseClient(this);
	private ProgressDialog progressDialog;
	private DrinkItemizedOverlay allItemizedOverlay;
	List<Overlay> mapOverlays;
	Geocoder geoCoder;
	private Drawable drawableDrink, drawableEat, drawableMyLocation;
	MyLocationItemizedOverlay myLocationItemizedOverlay;
	private Facebook mFacebook;
	SharedPreferences prefs;
	private DetailPopupLayoutData dpld;
	private RangeSeekBar<Integer> timeSeekBar;
	private boolean menuAddClicked = false;
	private Business businessToFocus;
	private int startHourSyncDelta = 0, syncDelta = 1;
	private boolean need_to_focus=false;

	// --preferences--
	public int rating_thr = 0;
	public int money_thr = 0;
	public String facebook_user = "";
	public String facebook_mail = "";
	public String facebook_image = "";
	public String facebook_image_small = "";
	public int business_type_btm = QueryData.ALL_TYPES;
	private static AndroAppActivity instance;
	// ---------------

	// Constants
	final int ADD_NEW_BUSINESS = 0;
	final int OPEN_LIST_VIEW = 1;
	private String PREF_CHANGED = "PREF_CHANGED";
	final static int SHOW_SYSTEM_SETTINGS = 4;
	final static int TO_MAP = 1;
	public static final String APP_ID = "303549773019655";
	public static final String PREF_DRINK_BUTTON_VISIBLE = "PREF_DRINK_BUTTON_VISIBLE";
	public static final String PREF_EAT_BUTTON_VISIBLE = "PREF_EAT_BUTTON_VISIBLE";
	public static final String PREF_PARTY_BUTTON_VISIBLE = "PREF_PARTY_BUTTON_VISIBLE";

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		instance = this;

		Log.w("AndroApp", "Starting onCreate");
		
		if (!isOnline()){
			Log.e("NetworkError", "No internet");
			
			AlertDialog.Builder builder = new AlertDialog.Builder(this);
			builder.setMessage("Internet connection is not available. Do you want to enable Internet connection?")
					.setPositiveButton("Ok",
							new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface dialog,
										int id) {
									startActivityForResult(new Intent(android.provider.Settings.ACTION_WIRELESS_SETTINGS), SHOW_SYSTEM_SETTINGS);
								}
							})
					.setNegativeButton("Cancel",
							new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface dialog,
										int id) {
									return;
								}
							}).show();		
		}
			
		mapView = (ObservableMapView) findViewById(R.id.main_mapview);
		mapView.setBuiltInZoomControls(true);

		// Assigning map controller
		mapController = mapView.getController();
		mapController.setZoom(14);
		mapView.setMapViewListener(new MapViewListener (){
			public void onPan(GeoPoint oldTopLeft, GeoPoint oldCenter,
					GeoPoint oldBottomRight, GeoPoint newTopLeft,
					GeoPoint newCenter, GeoPoint newBottomRight) {
				// TODO Auto-generated method stub
				
			}
			public void onZoom(GeoPoint oldTopLeft, GeoPoint oldCenter,
					GeoPoint oldBottomRight, GeoPoint newTopLeft,
					GeoPoint newCenter, GeoPoint newBottomRight,
					int oldZoomLevel, int newZoomLevel) {
				// TODO Auto-generated method stub
				Log.w("Zoom","Current zoom = " + mapView.getZoomLevel());
				updateMapWithItemizedOverlay();
				
			}
			public void onClick(GeoPoint clickedPoint) {
				// TODO Auto-generated method stub
				
			}
		}
		);

		// get the overlays list form the mapView (which hold it)
		mapOverlays = mapView.getOverlays();

		/*---------------------------Start at current phone location-----------------------------*/

		UpdateLocation();
		
		// lm.requestLocationUpdates(bestProvider, 1000L, 500.0f, this);
		// currentGeoPoint = new GeoPoint((int)
		// (lm.getLastKnownLocation(bestProvider).getLatitude() * 1E6), (int)
		// (lm.getLastKnownLocation(bestProvider).getLongitude() * 1E6)) ;

		// moveToLocation();

		/* ------------------ Get time ----------------- */

		c = Calendar.getInstance();
		c.getTime();

		/*-----------------------------------------Update system preferences-------------------------------------------------*/

		mFacebook = new Facebook(APP_ID);
		updateFromPreferences();
		Log.w("AndroApp", "Facebook user - " + facebook_user);

		/*-----------------------------adding icon to the map -------------------------------------------*/

		// prepare recourses

		// Preparing a geocoder to get geopoints by address.
		geoCoder = new Geocoder(this, Locale.ENGLISH);

		// drawbles
		drawableDrink = this.getResources().getDrawable(R.drawable.drink1_icon);
		drawableEat = this.getResources().getDrawable(R.drawable.eat1_icon);

		refreshData(startHourSyncDelta, syncDelta);

		/*--------------------------------------Capture touch events------------------------------------------------*/
		mapOverlays.add(new Overlay() {
			public boolean onTouchEvent(MotionEvent e, MapView mapView) {
				mGestureDetector.onTouchEvent(e);
				return super.onTouchEvent(e, mapView);
			}

		});

		mGestureDetector = new GestureDetector(
				new GestureDetector.SimpleOnGestureListener() {
					// add from menu
					public boolean onSingleTapConfirmed(MotionEvent e) {
						if (menuAddClicked) {
							isPopupExist = true;
							menuAddClicked = false;
							openAddPopupWindow(e);
						}
						return true;
					}

					// open add popup in location after long press
					@Override
					public void onLongPress(MotionEvent e) {
						isPopupExist = true;
						openAddPopupWindow(e);
					}

					@Override
					public boolean onDoubleTap(MotionEvent e) {
						mapController.zoomIn();
						return true;
					}

					// remove the popup & time scorller if press off screen.
					@Override
					public boolean onDown(MotionEvent e) {
						if (isPopupExist) {
							mapView.removeView(addPopupView);
							isPopupExist = false;
						}
						if (dpld != null) {
							dpld.setVisibilty(false);
							if (allItemizedOverlay != null)
								allItemizedOverlay.defaultSelectedItem();

						}
						if (timeLayout != null) {
							timeLayout.setVisibility(View.GONE);
						}
						return true;
					}
				});
		/*-----------------------------------------------------------------------------------------------------------------------*/
		/*---------------------------------------------------Attach interface----------------------------------------------------*/
		/*-----------------------------------------------------------------------------------------------------------------------*/

		/*-------------------------------Set Drink Button---------------------------------------------*/
		// final ImageButton drinkButton = (ImageButton)
		// findViewById(R.id.main_drink_button);
		// drinkButton.setOnClickListener(new OnClickListener() {
		// public void onClick(View v) {
		// if (isDrinkVisible){
		// mapOverlays.remove(drinkItemizedOverlay);
		// isDrinkVisible = false;
		// Editor editor = prefs.edit();
		// editor.putBoolean(PREF_DRINK_BUTTON_VISIBLE, false);
		// editor.commit();
		// mapView.invalidate();
		//
		// }
		// else {
		// if (drinkList != null && drinkList.size() > 0 && drinkItemizedOverlay
		// != null){
		// mapOverlays.add(drinkItemizedOverlay);
		// isDrinkVisible = true;
		// Editor editor = prefs.edit();
		// editor.putBoolean(PREF_DRINK_BUTTON_VISIBLE, true);
		// editor.commit();
		// mapView.invalidate();
		// }
		// }
		// }
		// });
		//
		// /*-------------------------------Set Eat
		// Button---------------------------------------------*/
		// Log.i("EatButton", "isEatVisible: " + isEatVisible);
		// final ImageButton eatButton = (ImageButton)
		// findViewById(R.id.main_eat_button);
		// eatButton.setOnClickListener(new OnClickListener() {
		// public void onClick(View v) {
		// Log.i("EatButton", "isEatVisible: " + isEatVisible);
		// if (isEatVisible){
		// mapOverlays.remove(eatItemizedOverlay);
		// isEatVisible = false;
		// Editor editor = prefs.edit();
		// editor.putBoolean(PREF_EAT_BUTTON_VISIBLE, false);
		// editor.commit();
		// mapView.invalidate();
		//
		// }
		// else {
		// if (eatList != null && eatList.size() > 0 && eatItemizedOverlay !=
		// null){
		// mapOverlays.add(eatItemizedOverlay);
		// isEatVisible = true;
		// Editor editor = prefs.edit();
		// editor.putBoolean(PREF_EAT_BUTTON_VISIBLE, true);
		// editor.commit();
		// mapView.invalidate();
		// }
		// }
		// }
		// });

		/*-------------------------------Set List Button---------------------------------------------*/
		final ImageButton listButton = (ImageButton) findViewById(R.id.main_list_button);
		listButton.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				openListView();
			}
		});

	}

	

	/**
	 * handling the event of openning the add new location popup
	 * 
	 * @param e
	 *            : the touch event
	 */
	protected void openAddPopupWindow(MotionEvent e) {

		// create the popup view
		addPopupView = getLayoutInflater().inflate(R.layout.add_popup_layout,
				mapView, false);

		// get the geo point from where the screen touched
		currentGeoPoint = mapView.getProjection().fromPixels((int) e.getX(),
				(int) e.getY());

		// create map parmeter to place the popup
		MapView.LayoutParams mapParams = new MapView.LayoutParams(150, 60,
				currentGeoPoint, 15, 0, MapView.LayoutParams.BOTTOM
						| MapView.LayoutParams.CENTER);

		// add the popup to the map.
		mapView.addView(addPopupView, mapParams);

		// attach the image Button from the popup to ImageButton object, and add
		// listener.
		Button addPopupButton = (Button) addPopupView
				.findViewById(R.id.add_popup_add_button);

		addPopupButton.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				// check facebook user session
				addNewBusinessLoginCheck();
			}
		});
	}

	@Override
	protected boolean isRouteDisplayed() {
		return false;
	}

	/*-----------------------Location Listener Function-----------------------------------------*/

	/**
	 * Implementation for location listener
	 */
	public void onLocationChanged(Location location) {
		Log.w("LocationTracking", "Location Changed");
		if (location != null) {
			// double lat = location.getLatitude();
			// double lng = location.getLongitude();
			// GeoPoint p = new GeoPoint((int) lat * 1000000, (int) lng *
			// 1000000);
			// mapController.animateTo(p);
			moveToLocation(location);
		}
	}

	/**
	 * Implementation for location listener
	 */
	public void onProviderDisabled(String provider) {
		Log.e("LocationTracking", "Provider disabled");
		Toast.makeText(AndroAppActivity.this,
				"Please enable location provider", Toast.LENGTH_LONG)
				.show();
		UpdateLocation();
		
	}

	/**
	 * Implementation for location listener
	 */
	public void onProviderEnabled(String provider) {
		Log.w("LocationProvider", "Provider enabled");
		UpdateLocation();
		this.onRestart();
	}

	/**
	 * Implementation for location listener
	 */
	public void onStatusChanged(String provider, int status, Bundle extras) {
		moveToLocation();

	}

	/**
	 * Move the map to a location, and pin an icon there.
	 * 
	 * @param location
	 *            - the location to move too.
	 */
	private void moveToLocation(Location location) {
		if (location != null) {
			Log.w("LocationAccuracy", Float.toString(location.getAccuracy()));
			Double lat = location.getLatitude() * 1E6;
			Double lng = location.getLongitude() * 1E6;
			GeoPoint p = new GeoPoint(lat.intValue(), lng.intValue());
			 currentGeoPoint = p;
			if (mapController != null)
				mapController.animateTo(p);

			pinLocation(p);
		} else {
			Log.e("LocationBug", "Couldn't find location");
		}
	}

	/**
	 * In case no location provided, get lastKnownsLocation with the last known
	 * bestProvider
	 */
	private void moveToLocation() {
		if (lm != null && bestProvider != null) {
			Location location = lm.getLastKnownLocation(bestProvider);
			moveToLocation(location);
		}
	}

	/**
	 * Pin location on the map (only one at a time)
	 * 
	 * @param p
	 *            - a GeoPoint to pin the location on
	 */
	private void pinLocation(GeoPoint p) {
		Log.w("LocationPin", "Pinning location on the map");
		if (mapOverlays != null) {
			if (myLocationItemizedOverlay == null) {
				drawableMyLocation = this.getResources().getDrawable(
						R.drawable.location_icon);
				myLocationItemizedOverlay = new MyLocationItemizedOverlay(
						drawableMyLocation);
			}
			mapOverlays.remove(myLocationItemizedOverlay);
			myLocationItemizedOverlay.removeAllOverlays();

			myLocationItemizedOverlay.addOverlay(new OverlayItem(p,
					"My location", "Here"));
			mapOverlays.add(myLocationItemizedOverlay);
		}
	}
	
	/*-----------------------------------------Network-------------------------------------------------*/
	public boolean isOnline() {
		 final ConnectivityManager conMgr = (ConnectivityManager) getSystemService (Context.CONNECTIVITY_SERVICE);
		 if (conMgr == null)
			 Log.e("Connectivity manager", "Null pointer");
		 
         if (conMgr.getActiveNetworkInfo() != null && conMgr.getActiveNetworkInfo().isAvailable() &&    conMgr.getActiveNetworkInfo().isConnectedOrConnecting()) {
               return true;
         } else {
               System.out.println("Internet Connection Not Present");
             return false;
         }
	}
	
	public void reload() {

	    Intent intent = getIntent();
	    overridePendingTransition(0, 0);
	    intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
	    finish();

	    overridePendingTransition(0, 0);
	    startActivity(intent);
	}

	/*-----------------------------------------Menu-----------------------------------------------------*/
	public boolean onCreateOptionsMenu(Menu menu) {
		// super.onCreateOptionsMenu(menu);

		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.layout.map_menu, menu);

		return true;
	}

	public boolean onPrepareOptionsMenu(Menu menu) {
		if (timeLayout != null) {
			timeLayout.setVisibility(View.GONE);
		}
		return true;
	}

	public boolean onOptionsItemSelected(MenuItem item) {
		// super.onOptionsItemSelected(item);

		switch (item.getItemId()) {
		case R.id.menu_time_scroll:
			runTimeScoll();
			return true;
		case R.id.menu_user_prefernce:
			Intent i = new Intent(this, PreferencesActivity.class);
			startActivity(i);
			return true;
		case R.id.menu_add:
			Toast.makeText(AndroAppActivity.this,
					"Please choose location to add new deal", Toast.LENGTH_LONG)
					.show();
			menuAddClicked = true;
			return true;

		}

		return false;
	}

	private void updateFromPreferences() {
		Log.i("AndroApp", "Updating User Preference");
		Context context = getApplicationContext();
		prefs = PreferenceManager.getDefaultSharedPreferences(context);

		rating_thr = prefs.getInt(PreferencesActivity.PREF_RATING_THREHOLD, 0);
		if ((rating_thr < 1) || (rating_thr > 5))
			rating_thr = 1;

		money_thr = prefs.getInt(PreferencesActivity.PREF_MONEY_THREHOLD, 0);
		if ((money_thr < 1) || (money_thr < 3))
			money_thr = 1;

		if (SessionStore.restore(mFacebook, this)) {
			facebook_user = prefs.getString(
					PreferencesActivity.PREF_FACEBOOK_USER, "");
			facebook_mail = prefs.getString(
					PreferencesActivity.PREF_FACEBOOK_MAIL, "");
			facebook_image = prefs.getString(
					PreferencesActivity.PROFILE_PIC_URL, "");
			facebook_image_small = prefs.getString(
					PreferencesActivity.PROFILE_PIC_URL_SMALL, "");
		} else {
			facebook_user = "";
			facebook_mail = "";
			facebook_image = "";
			facebook_image_small = "";
		}

		isDrinkVisible = prefs.getBoolean(PREF_DRINK_BUTTON_VISIBLE, true);
		isEatVisible = prefs.getBoolean(PREF_EAT_BUTTON_VISIBLE, true);
		isPartyVisible = prefs.getBoolean(PREF_PARTY_BUTTON_VISIBLE, true);

		business_type_btm = 0;

		if (isDrinkVisible)
			business_type_btm |= QueryData.PUB;

		if (isEatVisible)
			business_type_btm |= QueryData.REST;

		if (isPartyVisible)
			business_type_btm |= QueryData.PARTY;

	}

	/**
	 * Create a SeekBar, bind it, and present it on the map.
	 */
	private void runTimeScoll() {
		timeLayout = (LinearLayout) findViewById(R.id.main_time_layout);

		timeLayout.setVisibility(View.VISIBLE);
		timeText = (TextView) findViewById(R.id.main_text_time);

		if (timeSeekBar == null) {
			// create RangeSeekBar as Integer range between 0 and 12
			timeSeekBar = new RangeSeekBar<Integer>(0, 12,
					AndroAppActivity.this);
			timeSeekBar
					.setOnRangeSeekBarChangeListener(new OnRangeSeekBarChangeListener<Integer>() {
						public void rangeSeekBarValuesChanged(Integer minValue,
								Integer maxValue, boolean need_sync) {
							// handle changed range values
							TimeBarHoursUpdate(minValue, maxValue, need_sync);
						}
					});
			timeSeekBar.setNotifyWhileDragging(true);
			timeLayout.addView(timeSeekBar);
			timeSeekBar.setSelectedMinValue(0);
			timeSeekBar.setSelectedMaxValue(1);
			TimeBarHoursUpdate(0, 1, false);
		}
	}

	/*--------------------------------------------------OnSeekerBarListener Functions----------------------------------------*/

	public void TimeBarHoursUpdate(int minValue, int maxValue, boolean need_sync) {
		// current calendar
		c = Calendar.getInstance();
		Date currentDate = c.getTime();
		int hour = Utils.hourAfterHourAdd(currentDate.getHours(), minValue);
		String startHour = hour + ":00";
		hour = Utils.hourAfterHourAdd(hour, maxValue - minValue);
		String endHour = hour + ":00";

		timeText.setText("Deals relevant from " + startHour + " to " + endHour);

		if (need_sync) {
			startHourSyncDelta = minValue;
			syncDelta = maxValue - minValue;
			refreshData(startHourSyncDelta, syncDelta);
		}
	}

	/*--------------------------------------------------------------------------------------------------------------------*/
	/*-----------------------------------------Misc Functions ------------------------------------------------------------*/
	/*--------------------------------------------------------------------------------------------------------------------*/

	/*--------------------------------------Map update Functions----------------------------------------------------------*/

	/**
	 * Update the DataBaseClient with the server 1) sync with server (using
	 * sync()) 2) update the map.
	 */
	public void refreshData() {
		refreshData(0, 1);
	}

	public void refreshData(int deltaStart, int delta) {
		if (dpld == null)
			initiateDPLD();

		Log.w("AndroApp", "Refreshing application");
		// current calendar
		c = Calendar.getInstance();
		Date currentDate = c.getTime();
		// String date = pad(currentDate.getDate()) + "/" +
		// pad(currentDate.getMonth()) + "/" + pad(currentDate.getYear());

		int bitMapDay = intDayToBitmap(currentDate.getDay());
		int min = currentDate.getMinutes();
		int hour = Utils.hourAfterHourAdd(currentDate.getHours(), deltaStart);
		if (Utils.dayAfterHourAdd(currentDate.getHours(), deltaStart) == 1)
			bitMapDay = Utils.bmp_next_day(bitMapDay);

		String time = Utils.pad(hour) + ":" + Utils.pad(min);

		String strDay = String.valueOf(bitMapDay);

		// Sync with server
		Log.i("Time", "time query :" + time);
		dbc.sync("Israel", "Tel Aviv", Integer.toString(business_type_btm),
				strDay, time, Integer.toString(delta));

		// "Israel", "Tel Aviv", strDay, time, "1"
		progressDialog = new ProgressDialog(this);
		// Present dialog
		Log.i("AndroApp", "Getting data");
		onStartOfData();
	}

	void RefreshData(List<Business> lb) {

		// current calendar
		c = Calendar.getInstance();
		Date currentDate = c.getTime();
		// String date = pad(currentDate.getDate()) + "/" +
		// pad(currentDate.getMonth()) + "/" + pad(currentDate.getYear());
		String strDay = String.valueOf(intDayToBitmap(currentDate.getDay()));

		String time = Utils.pad(currentDate.getHours()) + ":"
				+ Utils.pad(currentDate.getMinutes());

		// Sync with server
		dbc.syncGeoPoint(lb, "Israel", "Tel Aviv", strDay, time, "1");

		// "Israel", "Tel Aviv", strDay, time, "1"
		progressDialog = new ProgressDialog(this);
		// Present dialog
		Log.i("AndroApp", "Getting data");
		onStartOfData();
	}

	public static int intDayToBitmap(int day) {
		Log.w("dayBitmap", "The day is - " + day);
		switch (day) {
		case 0:
			return QueryData.SUNDAY;
		case 1:
			return QueryData.MONDAY;
		case 2:
			return QueryData.TUESDAY;
		case 3:
			return QueryData.WEDNESDAY;
		case 4:
			return QueryData.THURSDAY;
		case 5:
			return QueryData.FRIDAY;
		case 6:
			return QueryData.SATURDAY;
		case 7:
			return QueryData.SUNDAY;

		}
		return 0;
	}

	private int intDayToBitmap(List<Integer> list) {
		int result = 0;

		for (int i = 0; i <= list.size() - 1; i++) {
			result |= intDayToBitmap(list.get(i));
		}

		return result;

	}
	
	

	/**
	 * Handle all the aspects of adding icons to the map (include update lists)
	 */
	private void updateMapWithItemizedOverlay() {

		allList = arrangeBusinessList();
		Log.w("updateMapWith",
				"UpdateuMapWith Preference for " + allList.size());

		if (allItemizedOverlay == null)
			allItemizedOverlay = new DrinkItemizedOverlay(drawableDrink, this,
					allList, mapView, dpld);

		mapOverlays.remove(allItemizedOverlay);

		allItemizedOverlay.removeAllOverlays();
		allItemizedOverlay.setBusinessList(allList);
		populateItemizedOverlay(allItemizedOverlay, allList, geoCoder, "");
		allItemizedOverlay.setAllIconsToDefault();
		if (allList != null && allList.size() > 0
				&& allItemizedOverlay.size() > 0)
			mapOverlays.add(allItemizedOverlay);

		mapView.invalidate();
	}

	private List<Business> arrangeBusinessList() {
		// add put all in the list
		allList = getListByPrefernceRating();
		
		String like_str = prefs.getString(PreferencesActivity.PREF_LIKES, "");
		
		Log.i("AndroApp","Arranging Businesses");
		
		if (like_str!=null){
			Log.i("AndroApp","Likes String: " + like_str);
			
			List<String> likes = Arrays.asList(like_str.split("#"));
			
			List<Business> temp1 = new ArrayList<Business>();
			List<Business> temp2 = new ArrayList<Business>();
			for (Business b:allList){
				if (likes.contains(String.valueOf( b.getDealMaxRate().getDeal_type()))){
					temp1.add(b);
				}
				else
				{
					temp2.add(b);
				}
			}
			allList = temp1;
			allList.addAll(temp2);
		}

		return allList;
	}

	/**
	 * for each business, find it's location (by calling b.getFullLocation) with
	 * the geocoder. then create a new OverlayItem and add it to the
	 * ItemizedOverlay
	 * 
	 * @param itemizedOverlay
	 * @param businessList
	 * @param geoCoder
	 */
	private void populateItemizedOverlay(DrinkItemizedOverlay itemizedOverlay,
			List<Business> businessList, Geocoder geoCoder, String type) {
		if (businessList != null && businessList.size() > 0) {
			Log.w("updateMapWith", "Popuplating: " + businessList.size());
			// for each business, create overlayItem with geopoint by it's full
			// address
			int dist_thr;
			switch (mapView.getZoomLevel()){
				case 13:
					dist_thr = 400;
				break;
				case 14:
					dist_thr = 300;
				break;
				case 15:
					dist_thr = 200;
				break;
				case 16:
					dist_thr = 150;
				break;
				case 17:
					dist_thr = 50;
				break;
				case 18:
					dist_thr = 20;
				break;
				case 19:
					dist_thr = 10;
				break;
				case 20:
					dist_thr = 5;
				break;
				default:
					dist_thr = 3000;
				break;
			}
			
			List<Business> unsyncList = new ArrayList<Business>();
			
			boolean [] added_list = new boolean[businessList.size()];
			
			for (int i=0;i< businessList.size();i++){
				Business b = businessList.get(i); 
				boolean need_to_add = true;
				for (int j=0;j<i;j++){
					if (added_list[j]){
						Business b2 = businessList.get(j);
						float[] results = new float[3];
						Location.distanceBetween(((double)b.getLatitude()) / 1E6,((double) b.getLongitude())/ 1E6,((double) b2.getLatitude())/ 1E6, ((double)b2.getLongitude()) / 1E6, results);
						if ( results[0] < dist_thr ){
							need_to_add = false;
							break;
						}
					}
				}
				
				if (need_to_add){
					addBusinessToItemizedOverlay(b, itemizedOverlay, geoCoder,
							unsyncList, b.getType());
					added_list[i]=true;
				}
				else
				{
					added_list[i]=false;
				}
			}
			
			if (!unsyncList.isEmpty())
				RefreshData(unsyncList);
		}
	}

	private void addBusinessToItemizedOverlay(Business b,
			DrinkItemizedOverlay itemizedOverlay, Geocoder geoCoder,
			List<Business> unsyncList, String type) {
		DrawableHolder dh = getBusinessDrawbleHolder(b.getDealMaxRate(), type);

		try {
			GeoPoint p = b.getGeoPoint();
			if (p == null) {
				Log.i("GeoPoint", "need to update geopoint - " + b.getName());

				List<Address> foundAddress = geoCoder.getFromLocationName(
						b.getFullAddress(), 1);
				if (foundAddress != null && foundAddress.size() > 0) {
					p = new GeoPoint(
							(int) (foundAddress.get(0).getLatitude() * 1E6),
							(int) (foundAddress.get(0).getLongitude() * 1E6));

					b.setGeoPoint(p);
					unsyncList.add(b);
					Log.i("GeoPoint", "nPushed to sync list");
					itemizedOverlay.addOverlay(new OverlayItemDrawable(p, b
							.getName(), b.getType(), dh));
				} else {
					Log.e("GeoPoint", "Cann't find geopoint - " + b.getName());
				}
			} else {
				itemizedOverlay.addOverlay(new OverlayItemDrawable(p, b
						.getName(), b.getType(), dh));
			}

		} catch (IOException e) {
			Log.w("Populate",
					"Couldn't find address for business" + b.getName());
			Log.e("DEBUGTAG", "!!!!!!!!!!!!Can't find Address!!!!!!!!!!!!!!!!",
					e);
		}
	}

	/**
	 * Return correct DrawableHolder according to b.getDealMaxRate type and
	 * source
	 * 
	 * @param b
	 * @return DrawbableHolder
	 */
	private DrawableHolder getBusinessDrawbleHolder(Deal d, String type) {
		if (type.equalsIgnoreCase("pub"))
			return PicturesUtil.getBusinessDrawableHodler(d, PicturesUtil.PUB,
					this);
		else if (type.equalsIgnoreCase("rest"))
			return PicturesUtil.getBusinessDrawableHodler(d, PicturesUtil.REST,
					this);
		else
			return PicturesUtil.getBusinessDrawableHodler(d,
					PicturesUtil.PARTY, this);
	}

	/**
	 * Opening an Add popup, and call the AddNewBusiness activity to handle the
	 * add business
	 */
	private void addNewBusinessLoginCheck() {

		if (!SessionStore.restore(mFacebook, this)) {
			AlertDialog.Builder builder = new AlertDialog.Builder(this);
			builder.setMessage("You need to login with your facebook account!")
					.setPositiveButton("Ok",
							new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface dialog,
										int id) {
									Intent i = new Intent(
											AndroAppActivity.this,
											PreferencesActivity.class);
									startActivity(i);
								}
							})
					.setNegativeButton("Cancel",
							new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface dialog,
										int id) {
									return;
								}
							}).show();

		} else {
			addNewBusinessDidYouMean();
		}

	}

	private void addNewBusinessDidYouMean() {
		// Get the address of the location
		Geocoder geocoder = new Geocoder(this, Locale.ENGLISH);

		try {
			currAddress = geocoder.getFromLocation(
					currentGeoPoint.getLatitudeE6() / 1E6,
					currentGeoPoint.getLongitudeE6() / 1E6, 2).get(0);

		} catch (IOException e1) {
			Log.e("DEBUGTAG", "!!!!!!!!!!!!Can't find Address!!!!!!!!!!!!!!!!",
					e1);
		}

		Log.i("Close Businesses", "Looking for close businesses!");

		final List<Entry<Integer, Business>> tempMap = dbc.getListbyDistance(
				"all", currentGeoPoint, geocoder, 1E3);
		if (!tempMap.isEmpty()) {
			final CharSequence[] items = new CharSequence[tempMap.size() + 1];
			int i = 0;
			for (Entry<Integer, Business> ent : tempMap) {
				Log.i("Close Businesses", ent.getValue().getName());
				items[i++] = ent.getValue().getName();
			}
			items[i] = "Add new business...";

			new AlertDialog.Builder(this).setTitle("Did you mean?")
					.setItems(items, new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog, int which) {
							Log.i("Close Businesses", (String) items[which]);

							if (which == (items.length - 1)) {
								CreateNewBusiness = true;
								addNewBusiness();
							} else {
								CreateNewBusiness = false;
								currBusiness = tempMap.get(which).getValue();
								currAddress = null;
								addNewBusiness();
							}
						}
					}).show();
		} else {
			CreateNewBusiness = true;
			addNewBusiness();
		}
	}

	private void addNewBusiness() {
		// open the window
		Intent addNewBusinessIntent = new Intent(this, AddNewBusiness.class);
		Bundle bundle = new Bundle();

		bundle.putBoolean("CreateNewBusiness", CreateNewBusiness);

		if (CreateNewBusiness) {
			if (currAddress != null) {
				bundle.putString("address", currAddress.getThoroughfare());
			} else {
				bundle.putString("address", "Address unknown");
			}
		} else {
			bundle.putParcelable("business", currBusiness);
		}

		addNewBusinessIntent.putExtras(bundle);
		startActivityForResult(addNewBusinessIntent, ADD_NEW_BUSINESS);
	}

	/**
	 * Handling all the returns from other activities.
	 */
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);

		switch (requestCode) {
		case ADD_NEW_BUSINESS:
			Log.i("AndroApp", "Back add");
			if (resultCode == RESULT_OK) {
				Bundle b = data.getExtras();
				NewDealData ndd = b.getParcelable("data");

				// prepare delta
				int deltaHour = ndd.getEndHour() - ndd.getStartHour();
				if (deltaHour <= 0)
					deltaHour += 24;

				// prepare comment

				Log.i("AndroApp", "Adding new business");

				if (CreateNewBusiness) {

					dbc.AddDeal(
							currentGeoPoint,
							ndd.getName(),
							currAddress.getCountryName(),
							currAddress.getLocality(),
							currAddress.getThoroughfare(),
							-1,
							"",
							ndd.getType().toLowerCase(),
							"",
							ndd.getComment(),
							"",
							Utils.pad(ndd.getStartHour()) + ":"
									+ Utils.pad(ndd.getStartMin()), ""
									+ deltaHour, ndd.getDay(), ndd.getRate(),
							ndd.getMoney());
				} else {
					dbc.AddDeal(
							currBusiness,
							ndd.getName(),
							ndd.getComment(),
							Utils.pad(ndd.getStartHour()) + ":"
									+ Utils.pad(ndd.getStartMin()), ""
									+ deltaHour, ndd.getDay(), ndd.getRate(),
							ndd.getMoney());
				}
				refreshData(startHourSyncDelta, syncDelta);

				if (isPopupExist) {
					mapView.removeView(addPopupView);
					isPopupExist = false;
				}
			}
			break;
			
		case SHOW_SYSTEM_SETTINGS:
			Log.i("AndroApp", "Back from SYSTEM SETTINGS");
//			if (resultCode == RESULT_OK) {
//				// refresh the lists
//				updateFromPreferences();
//				refreshData(startHourSyncDelta, syncDelta);
//				Log.w("AndroApp", facebook_user + " - " + facebook_mail);
//			}
			
			final ProgressDialog pd = new ProgressDialog(this);  
			pd.setMessage("Tring to connect to the network...");
			pd.show();		
			Thread t = new Thread() {
		        @Override
		        public void run() {
		            try {
		                int i=0;
		            	while ( (!isOnline()) && (i<8) ) {
		                    //Wait to connect
		                	Log.i("WatingTread","Still waiting for wi-fi...");
		                    Thread.sleep(1000);
		                    i++;
		                }
		            	pd.dismiss();
		                reload();
		            } catch (Exception e) {
		            }
		        }
		    };
		    t.start();
		    break;	
			
		}
	}

	@Override
	public void onNewIntent(Intent intent) {
		super.onNewIntent(intent);
		setIntent(intent);
	}

	@Override
	public void onRestart() {
		super.onRestart();

		if (prefs.getBoolean(PREF_CHANGED , false))
		{
//			Editor editor = prefs.edit();
//			editor.putBoolean(PREF_CHANGED, false);
//			editor.commit();
			Log.i("AndroApp", "Back from preferences");
			// refresh the lists
			updateFromPreferences();
			refreshData(startHourSyncDelta, syncDelta);
			Log.w("AndroApp", facebook_user + " - " + facebook_mail);
		}
		
		Log.i("AndroApp", "Resuming...");
		Intent last_intent = getIntent();
		Bundle b = last_intent.getBundleExtra("values");
		updateMapWithItemizedOverlay();
		if (b != null) {
			Business currentBusiness = b.getParcelable("business");
			if (mapController != null) {
				//if (((businessToFocus == null) || (currentBusiness.getKey() != businessToFocus.getKey())) ) {
				if (businessToFocus == null) {
					Log.i("AndroApp", "Focusing on business");
					mapController.animateTo(currentBusiness.getGeoPoint());
					businessToFocus = currentBusiness;
					// select deal on map
					if (allItemizedOverlay!=null){
						Log.i("AndroApp", "Itimize overlay");
						allItemizedOverlay.selectBusiness(currentBusiness);
					}
					else
					{
						Log.i("AndroApp", "No itimezed overlay");
						need_to_focus=true;
					}

				}
			} else {
				Log.e("AndroApp", "No need to focus");
			}
		}
		else
		{
			Log.i("AndroApp", "No deal passed");
		}
	}

	/**
	 * Handling the moving to list view of the business.
	 */
	private void openListView() {
		Intent openListTabActivity = new Intent(this, ListTabActivity.class);
		Bundle bundle = new Bundle();

		// put all
		ArrayList<Business> allArrayList = new ArrayList<Business>(allList);
		bundle.putParcelableArrayList("all", allArrayList);

		openListTabActivity.putExtra("values", bundle);
		startActivityForResult(openListTabActivity, OPEN_LIST_VIEW);
	}

	/**
	 * Called from AddNewBusiness to indicate the start of grabing information
	 * from the net
	 */
	public void onStartOfData() {
		progressDialog.setMessage("Collecting Information...");
		progressDialog.show();
	}

	public void onEndOfData() {
		if (progressDialog.isShowing())
			progressDialog.dismiss();
		updateMapWithItemizedOverlay();
		if (need_to_focus){
			need_to_focus=false;
			allItemizedOverlay.selectBusiness(businessToFocus);
		}

	}

	/**
	 * note require a DataBaseClient already active.
	 * 
	 * @param string
	 *            - type of the business to get
	 * @return list of business from the DataBaseClient
	 */
	private List<Business> getListByPrefernceRating() {
		return dbc.getListbyRating(rating_thr, money_thr, currentGeoPoint);

	}

	/**
	 * note require a DataBaseClient already active.
	 * 
	 * @param string
	 *            - type of the business to get
	 * @return list of business from the DataBaseClient
	 */
	private List<Business> getListByPrefernceName() {
		return dbc.getListbyName(rating_thr, money_thr, currentGeoPoint);
	}

	private void initiateDPLD() {
		dpld = new DetailPopupLayoutData();

		View currentView = findViewById(android.R.id.content);
		dpld.attachAddressToView(currentView, R.id.main_detailes_address_text);
		dpld.attachBNameToView(currentView,
				R.id.main_detailes_business_name_text);
		dpld.attachDNameToView(currentView, R.id.main_detailes_deal_name_text);
		dpld.attachImageToView(currentView, R.id.main_detailes_image);
		dpld.attachLayoutToView(currentView, R.id.main_detailes_layout);
		dpld.attachMoneyToView(currentView, R.id.main_detailes_money_ratingbar);
		dpld.attachRateToView(currentView, R.id.main_detailes_stars_ratingbar);
		dpld.attachDistanceToView(currentView, R.id.main_detailes_distance_text);
	}

	public static AndroAppActivity getInstance() {
		return instance;
	}

	private void UpdateLocation() {
		lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
		Criteria crit = new Criteria();
		crit.setAccuracy(Criteria.ACCURACY_FINE);
		crit.setHorizontalAccuracy(Criteria.ACCURACY_HIGH);
		crit.setSpeedRequired(false);
		crit.setCostAllowed(true);
		crit.setPowerRequirement(Criteria.POWER_LOW);
		crit.setBearingRequired(false);

		bestProvider = lm.getBestProvider(crit, true);
		
		if (bestProvider != null)
		{
			location = lm.getLastKnownLocation(bestProvider);
			Log.w("LocationProvider", bestProvider);
		}
		
		if (location == null) {
			Log.e("LocationBug",
					"Location Instalization Bug - swithing to network");
			bestProvider = LocationManager.NETWORK_PROVIDER;
			location = lm.getLastKnownLocation(bestProvider);
		}
		
		if (location!=null)
			moveToLocation(location);
		
		if (bestProvider != null)
			lm.requestLocationUpdates(bestProvider, 20000, 50, this);

		if (bestProvider == null)
			Log.w("ProviderError", "Location provider not found");
		
		if (location == null)
			Log.w("LocationError", "Location not found");
		
	}
}